<template>
    <div class="product-box">
        <section>
            <div class="table">
                <!--   base-table 虚拟表格必须单独放一个父容器且只有一个元素           -->
                <base-table
                    ref="product-table"
                    :key="renderkEY"
                    :use-virtual="true"
                    :tableData="tableData"
                    :colunmData="column"
                    :disabled="disabled"
                    :totalColumn="totalColumn"
                    :tableConfig="{
                        isMultiSelect: false,
                        isIndex: true,
                        isShowOpera: true,
                        showSummary: true,
                        height: '49vh'
                    }"
                    @rowClick="viewSkuDetail"
                >
                    <template v-slot="{ scope }">
                        <el-button id="btn_t_gray" type="text" size="mini" :disabled="disabled" @click.stop.prevent="deleteItem(scope)">
                            {{ $t('layout.btns.delete') }}
                        </el-button>
                    </template>
                    <template v-slot:tableCell="{ scope: { row, item, $index } }">
                        <template v-if="item.type === 'image'">
                            <table-image :imageSrc="formatImageUrl(row['goodsCode'])" />
                        </template>
                        <template v-else-if="item.type === 'datePick'">
                            <base-date-picker :disabled="disabled || blackMap[item['id']]" class="no-border-input" :value.sync="row[item.value]" />
                        </template>
                        <!--对数量输入框判断 2 是普通物料  普通物料才可以手输入 -->
                        <template v-else-if="item.value === 'quantity'">
                            <base-input
                                v-if="row.goodsType === 2"
                                :value.sync="row[item.value]"
                                :disabled="disabled"
                                :type="item.type"
                                class="no-border-input number-input"
                                :inputProps="{
                                    decimalPlaces: decimalPlaces
                                }"
                                @input="singleGoodsInput($event, row)"
                            />
                            <el-button
                                v-else
                                type="text"
                                :disabled="disabled"
                                style="width: 100% !important"
                                class="hover number-input number-btn"
                                @click="changeNumber(row, $index)"
                            >
                                {{ culcalRowTotal(row.billSizeList, row) }}
                            </el-button>
                        </template>
                        <!-- 结算价格字段 需要做权限控制  有结算-->
                        <template v-else-if="item.value === 'balancePrice'">
                            <base-input
                                :value.sync="row[item.value]"
                                :disabled="item.isEdit ? !!blackMap[item['id']] : disabled"
                                :type="item.type"
                                :inputProps="{
                                    decimalPlaces: m_Price_Decimal_Places
                                }"
                                class="no-border-input number-input"
                                @input="balancePriceChange($event, row)"
                            />
                        </template>
                        <template v-else-if="item.value === 'discount'">
                            <base-input
                                :value="row[item.value] | fomartPercent"
                                :disabled="item.isEdit ? !!blackMap[item['id']] : disabled"
                                :type="item.type"
                                :inputProps="{
                                    clearable: false,
                                    suffixIcon: 'iconfont rbp-baifenbi'
                                }"
                                class="no-border-input number-input"
                                @blur="discountChange($event, row)"
                            />
                        </template>
                        <template v-else-if="['text', 'number'].includes(item.type)">
                            <base-input
                                :value.sync="row[item.value]"
                                :disabled="disabled || !!blackMap[item['id']]"
                                :type="item.type"
                                class="no-border-input number-input"
                            />
                        </template>
                        <template v-else-if="item.type === 'select'">
                            <base-select
                                :disabled="disabled || !!blackMap[item['id']]"
                                :value.sync="row[item.value]"
                                class="no-border-input"
                                :class="requireItem(item, row)"
                                :item="{
                                    options: item[item.value + '_options']
                                }"
                            />
                        </template>
                        <template v-else-if="item.fieldClass === 2">
                            <span class="pdl-10">{{ row.goodsFields ? row.goodsFields[item.value] : '' }}</span>
                        </template>
                        <template v-else-if="item.fieldClass === 3">
                            <span class="pdl-10">{{ row.customFields[item.value] }}</span>
                        </template>
                    </template>
                </base-table>
            </div>
            <base-pagination
                v-if="paginationStatus"
                :page="detailPage"
                :pageSizes="defaultPageSizes"
                @changePage="
                    (e) => {
                        paginationEvent('page', e);
                    }
                "
                @changePageSize="
                    (e) => {
                        paginationEvent('size', e);
                    }
                "
            />
        </section>
        <footer v-if="showSizeTable">
            <base-table
                ref="sizeTable"
                :use-virtual="true"
                :tableData="currentSizeTable"
                :colunmData="currentSizeData"
                class="size-table mgt-8"
                :tableConfig="{
                    isMultiSelect: false,
                    isIndex: true,
                    isShowOpera: false,
                    showSummary: true,
                    height: '20vh'
                }"
            />
        </footer>
        <base-dialog :dialogObj="sizeDialog" class="base-dialog" @confirm="confirm" @cancel="cancel">
            <template v-slot:content>
                <div class="size-box">
                    <p class="h4title">
                        {{ pop_skuName }}
                    </p>
                    <div style="height: 250px">
                        <base-table
                            key="size"
                            :use-virtual="true"
                            :tableData="pop_SkuTable"
                            :colunmData="pop_skeHeader"
                            class="size-table"
                            :tableConfig="{
                                isMultiSelect: false,
                                isIndex: false,
                                height: '200px',
                                isShowOpera: false,
                                showSummary: true
                            }"
                        >
                            <template v-slot:tableCell="{ scope: { row, item, index, $index } }">
                                <template v-if="item.type === 'number'">
                                    <input
                                        ref="pop-input"
                                        v-model.number="row[item.value]"
                                        class="pop-input"
                                        type="number"
                                        @focus="focus"
                                        @blur="blur"
                                        @keyup.stop.enter="pop_nextFocus($event, index + $index * row.inputLength)"
                                        @input="pop_inputValidate(row, item.value, row[item.value])"
                                    />
                                </template>
                            </template>
                        </base-table>
                    </div>
                </div>
            </template>
        </base-dialog>
    </div>
</template>

<script lang="ts">
import Component, { mixins } from 'vue-class-component';
import { DialogObj, Dictionary, PageObj, TableHeaderConfig } from '@/typings';
import { Prop, Watch } from 'vue-property-decorator';
import library from '@/library';
import { Tools } from '@/utils/tools';
import commonApi from '@/api/common-api';
import { divide, multiply } from '@/utils/accuracyLoss';
import { deepCopy } from '@/utils';
@Component({
    name: 'product-table',
    components: {
        baseTable: () => import('@/components/base-table/index.vue'),
        basePagination: () => import('@/components/base-pagination/index.vue'),
        tableImage: () => import('@/views/report-center/report-components/table-img.vue'),
        baseDatePicker: () => import('@/components/base-datePicker/index.vue'),
        baseInput: () => import('@/components/base-input/index.vue'),
        baseSelect: () => import('@/components/base-select/index.vue'),
        baseDialog: () => import('@/components/base-dialog/index.vue')
    }
})
export default class App extends mixins() {
    @Prop({ required: true }) column;
    @Prop({ required: true }) tableData;
    @Prop({ required: true }) disabled;
    @Prop({ required: true }) totalColumn;
    @Prop({ required: true }) status;
    @Prop({ default: () => {} }) config: Dictionary<any>;
    // 黑名单货品  列表中有对应这些货品 禁止修改【价格/等】 只能修改数量
    @Prop({
        required: false,
        default: () => {
            return [];
        }
    })
    blackGoodsList;
    get decimalPlaces() {
        return localStorage.getItem('Quantity_Decimal_Places') || 2;
    }
    get m_Price_Decimal_Places() {
        return Number(localStorage.getItem('Price_Decimal_Places')) || 2;
    }
    // 黑名映射集合 [数组转对象/减少遍历影响性能]
    blackMap: object = {};
    // 强制渲染值
    renderkEY: number = 0;
    // 是否显示分页器
    paginationStatus: boolean = false;
    // 分页器数据
    detailPage: PageObj = {
        pageSize: 25,
        pageNo: 1,
        total: 0,
        pageCount: 0
    };
    // 默认
    defaultPageSizes: number[] = [25, 50, 100, 200];
    // 是否显示尺码表格
    showSizeTable: boolean = false;
    // 尺码表头数据
    currentSizeData: any[] = [];
    // 尺码数据
    currentSizeTable: any[] = [];
    // 缓存尺码头数据
    skuHeaderCache: any = [];
    // 防抖
    timeOutDelay: any = null;
    // 弹窗配置
    sizeDialog: DialogObj = {
        isShowDialog: false,
        title: '',
        width: '50%'
    };
    // sku弹窗标题
    pop_skuName: string = '';
    // sku弹窗尺码数据
    pop_skeHeader: any[] = [];
    // sku弹窗尺码表头数据
    pop_SkuTable: TableHeaderConfig[] = [];
    // 表格当前索引
    tableIndex: number = 0;
    m_sizeHeader: any[] = [];
    @Watch('status')
    onStatusChange(value) {
        this.paginationStatus = !['edit', 'add'].includes(value);
    }
    @Watch('tableData.length')
    onTableDataChange(value) {
        if (value === 0) {
            // 数组长度为1 则清空所有数据
            this.tableIndex = 0;
            this.showSizeTable = false;
            this.currentSizeTable = [];
            this.m_sizeHeader = [];
        }
    }
    @Watch('blackGoodsList')
    onBlackChange(blackList) {
        console.log('黑名单', Tools.array2object('id', blackList));
        this.blackMap = Tools.array2object('id', blackList).success;
    }
    // 单一物料输入
    singleGoodsInput(value, row) {
        this.$set(row, 'quantity', Number(value));
        this.updateTable();
    }
    tableScroll(height) {
        (this.$refs['product-table'] as any).tableScroll(height);
    }
    setHighLightRow(row) {
        (this.$refs['product-table'] as any).setHighLightRow(row);
    }
    // 弹窗输入
    changeNumber(row, index) {
        this.tableIndex = index;
        // 如果是单一物料也不执行下面的逻辑 type === 2 是单一物料
        if (row.goodsType === 2) return;
        this.sizeDialog.isShowDialog = true;
        this.sizeDialog.title = this.$t('commonWord.inputNumber');
        // 获取该货品下面的sku数据
        // this.getSkuList(row);
        this.dealSkuInfo(row);
    }
    // 获取sku列表
    async getSkuList(row) {
        const res = await this._post({
            url: commonApi.getGoodsSku,
            params: {
                moduleId: this.$route.meta.moduleId,
                goodsId: row.goodsId
            }
        });
        if (res.code === 0) {
            this.dealSkuInfo(row, res.data);
        }
    }
    // 处理sku信息
    dealSkuInfo(row: Dictionary, data?: Dictionary<any[]>) {
        const { dataList, headerList } = row.goodsSkuDto;
        this.m_sizeHeader = [];
        this.currentSizeTable = [];
        if (!dataList) {
            this._message({ message: '没有尺码数据', type: 'warning' });
            this.currentSizeTable = [];
            return;
        }
        // 得到 sku 的数据
        this.pop_SkuTable = this.dealSkuData(dataList, row.billSizeList);
        this.pop_skuName = `${row.goodsName}-${row.goodsType === 1 ? '普通物料' : '单一物料'}`;
        // 得到sku 表头的数据
        this.pop_skeHeader = headerList.map((item) => {
            if (item.value.indexOf('s') === 0) {
                item.type = 'number';
                item.isShowTotal = true;
                item.width = '60px';
                this.m_sizeHeader.push(item.value);
                return item;
            } else {
                return {
                    ...item,
                    width: '60px'
                };
            }
        });
        this.pop_skeHeader.push({
            label: '合计',
            width: '60px',
            value: 'quantity',
            fixed: 'right',
            isShowTotal: true
        });
        // 合并小计行
        this.culcalSkuTotal(this.pop_SkuTable, row);
    }
    focus(e) {
        e.target.style.borderColor = 'blue';
    }
    blur(e) {
        e.target.style.borderColor = '';
    }
    // 处理sku尺码信息
    dealSkuData(dataList: any[], billSizeList: any[]) {
        const skuData: any[] = [];
        dataList.forEach((item) => {
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            const { refreneceList, sizeList, colorName, ...other } = item;
            const obj: Dictionary = Object.assign({}, other, {
                colorName: `${other.colorCode}-${colorName}`,
                oweQuantity: {}
            });
            if (sizeList.length) {
                sizeList.forEach((size, index) => {
                    // 这里是获取到对应尺码的数量
                    if (billSizeList) {
                        const sizeValueObj = billSizeList.find((sizeValue) => sizeValue.colorId === item.colorId && sizeValue.longId === item.longId);
                        if (sizeValueObj) {
                            obj[size.fieldName] = sizeValueObj[size.fieldName] || '';
                        }
                    }
                    obj.inputLength = index + 1;
                    obj.oweQuantity[size.fieldName] = size.oweQuantity;
                });
            }
            skuData.push(obj);
        });
        return skuData;
    }
    // 行点击
    viewSkuDetail(row) {
        if (!(row.billSizeList && row.billSizeList.length) || row['goodsType'] === 2) {
            this.showSizeTable = false;
            return;
        }
        this.showSizeTable = true;

        if (this.skuHeaderCache[row.goodsId]) {
            this.currentSizeData = this.skuHeaderCache[row.goodsId];
        } else {
            Tools.debounce(this.getSkuHeader(row.goodsId), 100);
        }

        row.billSizeList.forEach((item) => {
            if (item.colorName.indexOf(item.colorCode) === -1) {
                item.colorName = `${item.colorCode}-${item.colorName}`;
            }
        });
        this.currentSizeTable = row.billSizeList;
    }
    // 行删除
    deleteItem({ $index }) {
        (this as any).tableData.splice($index, 1);
    }

    // 行合计计算
    culcalRowTotal(arr: any[], row): number {
        if (!arr || arr.length === 0) return 0;
        const total = arr.reduce((prev, next) => {
            return prev + next.quantity;
        }, 0);
        this.$set(row, 'quantity', total);
        this.$set(row, 'totalAmount', (total * row.balancePrice).toFixed(2));
        return total;
    }
    // 图片格式化
    formatImageUrl(GoodsNo) {
        const server = localStorage.getItem('Inner_File_Service_Address');
        if (server && GoodsNo) {
            return `${server}/resource/goodsFile/${GoodsNo}.jpg`;
        } else {
            return library.placeholderGoods;
        }
    }
    // 价格类型
    balancePriceChange(value, row) {
        row.discount = divide(Number(value), row.tagPrice, 4);
        this.updateTable();
    }
    // 折扣
    discountChange(value, row) {
        value = (this as any)._isFloat(value) ? value : 0;
        row.discount = divide(value, 100, 4);
        row.balancePrice = multiply(row.tagPrice, row.discount, 2);
        this.updateTable();
    }
    // 必填项
    requireItem(item: Dictionary, row: Dictionary): string | void {
        if (item.required) {
            if (!row[item.value]) {
                return 'red-border';
            }
        }
    }
    // 分页器事件
    paginationEvent(type, e) {
        type === 'size' ? (this.detailPage['pageSize'] = e) : (this.detailPage['pageNo'] = e);
        this.$emit('update');
    }
    // 获取尺码头
    async getSkuHeader(goodsId) {
        const getSizeTableHeader = function (arr: any[]) {
            const currentSizeTable = arr.map((item) => {
                if (item.value === 'colorName' || item.value === 'longName') {
                    item.width = '110px';
                } else {
                    item.width = '60px';
                    item.isShowTotal = true;
                }
                return item;
            });
            // 增加合计行
            currentSizeTable.push({
                label: '合计',
                value: 'quantity',
                width: '110px',
                isShowTotal: true
            });
            return currentSizeTable;
        };
        const res = await this._post({
            url: commonApi.getGoodsSkuHeader,
            data: {
                data: {
                    moduleId: this.$route.meta.moduleId,
                    goodsId
                }
            }
        });
        if (res.code === 0) {
            this.currentSizeData = getSizeTableHeader(res.data);
            this.skuHeaderCache[goodsId] = this.currentSizeData;
        }
    }
    // 更新金额/视图面板
    updateTable() {
        // 更新视图面板
        this.$nextTick(() => {
            try {
                this.$store.dispatch(`${this.$route.meta.moduleId}/v_calculateBillTotalInfo`, (this as any).tableData);
            } catch (e) {
                console.log(e);
            }
        });
    }
    // 弹窗输入检验
    pop_inputValidate(row: Dictionary, key: string, value: number) {
        if (this.config.noValidate) {
            this.$emit('customerValidate', { row, key, value }, this.culcalSkuTotal);
            return;
        }
        if (isNaN(value)) {
            row[key] = 0;
        }
        if (Number(value) < 0) {
            this._message({ message: '不能输入负数', type: 'warning' });
            row[key] = 0;
        }
        row[key] = Number(row[key].toFixed(this.decimalPlaces));
        this.culcalSkuTotal(this.pop_SkuTable);
    }
    // 计算sku合计
    culcalSkuTotal(arr: any[] = this.pop_SkuTable, row?: Dictionary) {
        arr.forEach((item) => {
            item.quantity = 0;
            for (const k in item) {
                if (/^[s]\d+$/.test(k)) {
                    item.quantity = Number(item[k]) + Number(item.quantity);
                }
            }
        });
        if (row) {
            row.quantity = arr.reduce((prev, next) => {
                return prev + next.quantity;
            }, 0);
            row.totalAmount = (row.quantity * row.balancePrice).toFixed(2);
        }
    }
    // 弹窗确定
    confirm() {
        this.m_skuInputConfirm();
        this.$nextTick(() => {
            this.viewSkuDetail((this as any).tableData[this.tableIndex]);
        });
    }
    // 点击第一行
    viewFirstDetail() {
        setTimeout(() => {
            (this as any).tableData.length &&
                (() => {
                    this.viewSkuDetail((this as any).tableData[0]);
                    (this.$refs['product-table'] as any).setHighLightRow((this as any).tableData[0]);
                })();
        }, 500);
    }
    // 根据渠道价格类型更新价格
    async updateGoodsPrice(priceTypeId, channelId, rowExDate?) {
        if (channelId && priceTypeId) {
            const goodsIdArray = this.tableData.map((item) => {
                return item.goodsId;
            });
            const prop = {
                data: {
                    goodsIdList: goodsIdArray,
                    moduleId: this.$route.meta.moduleId,
                    channelId,
                    priceTypeId
                },
                pageCount: goodsIdArray.length,
                pageSize: 1
            };
            const res = await this._post({
                url: commonApi.goodsEntry,
                data: prop
            });
            if (res.code === 0) {
                for (let n = 0; n < this.tableData.length; n++) {
                    for (let m = 0; m < res.data.length; m++) {
                        if (this.tableData[n].goodsId === res.data[m].goodsId) {
                            Object.assign(this.tableData[n], res.data[m], rowExDate || {});
                            break;
                        }
                    }
                }
                this.updateTable();
            }
        } else {
            this.$message.warning('缺少价格类型/渠道,货品价格更新失败');
        }
    }
    m_skuInputConfirm() {
        // 往 tableData 里面增加尺码明细数据
        const sizeDetail: any[] = deepCopy(this.pop_SkuTable);
        // 这里只更新输入了的数据
        const updateSizeDetail = sizeDetail.filter((item) => {
            return this.m_sizeHeader.some((size) => item[size]);
        });
        this.$set((this as any).tableData[this.tableIndex], 'billSizeList', updateSizeDetail);
        this.updateTable();
        // 更新底部汇总
        const ref = this.$refs['product-table'] as any;
        ref && ref.updateFooter();
    }
    cancel() {
        if (!(this as any).tableData[this.tableIndex].billSizeList) {
            this.$set((this as any).tableData[this.tableIndex], 'billSizeList', []);
            this.$nextTick(() => {
                this.viewSkuDetail((this as any).tableData[this.tableIndex]);
            });
        }
    }
    pop_nextFocus(event: Event) {
        const classInput = Array.from(document.querySelectorAll('.pop-input'));
        const index = classInput.findIndex((item) => {
            return event.target === item;
        });
        const resultIndex = index + 1 >= classInput.length ? 0 : index + 1;
        (classInput[resultIndex] as any).focus();
    }
}
</script>

<style scoped lang="scss">
.pop-input {
    outline: none;
    width: 100%;
    height: 100%;
    display: block;
    text-align: center;
    background: rgba(231, 231, 231, 0.15);
    border: 1px solid rgba(0, 0, 0, 0);
}
.product-box {
    section {
        .table {
            height: 40vh;
        }
    }
    footer {
        height: 30vh;
    }
}
</style>
